﻿using LNet;
using OestsCommon.Model;
using OestsServer.Handlers;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using Utils;

namespace OestsServer.Net
{
    /// <summary>
    /// tcp通讯类(服务器)
    /// </summary>
    public abstract class ServerListener<Tclient> where Tclient : ClientChannel
    {
        public string IP { get; private set; }
        public abstract int Port { get; }
        public  ClientManager ClientManager  = new ClientManager();

        /// <summary>
        /// 处理器Namespace
        /// </summary>
        public virtual string HandlerNamspace { get; }

        protected abstract string ListenerName { get; }

        protected Socket serverSocket;

        /// <summary>
        /// 动态处理字典
        /// </summary>
        public Dictionary<PacketKey, HandlerBase<Tclient>> dicHandler = new Dictionary<PacketKey, HandlerBase<Tclient>>();


        public ServerListener()
        {
            RegisteHandler();
        }

        #region 动态数据
        public void RegisteHandler()
        {
            Type[] types = Assembly.GetCallingAssembly().GetTypes();
            foreach (var type in types)
            {
                if ((type.Namespace == HandlerNamspace) && type.Name.EndsWith("Handler"))
                {
                    object obj = Activator.CreateInstance(type);
                    HandlerBase<Tclient> handler = null;
                    handler = (HandlerBase<Tclient>)obj;

                    if (handler == null)
                    {
                        LogNetDebug.LogError("错误：handler is null ");
                        continue;
                    }
                    if (dicHandler.ContainsKey(handler.PKey))
                    {
                        LogNetDebug.LogError("注册 HandlerBase 错误，" + handler.PKey.ToString() + " 已经被注册！");
                    }
                    else
                    {
                        dicHandler.Add(handler.PKey, handler);
                    }
                }
            }
        }
        /// <summary>
        /// 解析数据包处理
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data"></param>
        public void Parse(Tclient client, Request packet)
        {
            if (dicHandler.ContainsKey(packet.RequestCode))
            {
                HandlerBase<Tclient> handler = dicHandler.TryGet(packet.RequestCode);
                try
                {
                    handler.Execute(client, packet);
                }
                catch (Exception e)
                {
                    //捕获处理器处理时发生的异常
                    LogNetDebug.LogError(packet.RequestCode + " : " + e.Message);
                }
            }
            else
            {
                string str = string.Format("【错误】【{0}】中未注册处理类【{1}】 ", client.GetType(), packet.RequestCode);
                LogNetDebug.LogError(str);

            }
        }

        #endregion

        /// <summary>
        /// 启动服务器
        /// </summary>
        public virtual void Listen()
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //获取本机IP
            string HostName = Dns.GetHostName();
            IPHostEntry IpEntry = Dns.GetHostEntry(HostName); //得到主机IP	
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            for (int i = 0; i < IpEntry.AddressList.Length; i++)
            {
                if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                {
                    ipAddress = IpEntry.AddressList[i];
                    break;
                }
            }
            serverSocket.Bind(new IPEndPoint(ipAddress, Port));
            serverSocket.Listen(1000);
            serverSocket.BeginAccept(AcceptCallBack, null);
            IP = ipAddress.ToString();
        }

        public abstract ClientChannel CreatClient(Socket socket);
        protected virtual void AcceptCallBack(IAsyncResult asyncResult)
        {
            Socket clientSocket = serverSocket.EndAccept(asyncResult);
            ClientManager.AddClient(CreatClient(clientSocket));

            string userIP = ((IPEndPoint)clientSocket.RemoteEndPoint).ToString();

            string info = string.Format("{0}[{1}]is connected !", ListenerName, clientSocket.RemoteEndPoint.ToString());
            LogNetDebug.Log(info);

            serverSocket.BeginAccept(AcceptCallBack, null);

        }


        public List<IpUser> GetOnlineUsers()
        {
            return ClientManager.GetOnlineUsers();
        }

        /// <summary>
        /// 下线账号
        /// </summary>
        /// <param name="userId"></param>
        public void LogoffAccount(int userId)
        {
            ClientManager.LogoffAccount(userId);
        }

        ~ServerListener()
        {
            dicHandler.Clear();
            serverSocket.Close();
        }
    }
}